/*
 * USART.cpp
 *
 * Created: 2012-05-10 10:13:42
 *  Author: Arni
 */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "USART.h"

// USART non-blocking transmission buffer and pointers
volatile uint8_t TXBUFFER[256];
volatile uint8_t TXHEAD = 0;
volatile uint8_t TXTAIL = 0;


void USART1_Init(void)
{
	// UBRRH/UCSRC are sharing the same I/O location
	// If writing to UBRRH the 8'th data bit (URSEL) must be cleared
	// If writing to UCSRC the 8'th data bit (URSEL) must be set
	//UBRRH = (BAUD_PRESCALE >> 8) & 0x0f;
	UBRRL = BAUD_PRESCALE;

	// Enable receiver and transmitter
	//RXCIE - 1 rx interrupt!
	UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); // _BV(UCSZ2) must be 0 if 8-bit data is selected

	// Set frame format: 8data, NoParity, 1 stop bit
	UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
}

//****************************************************
// Non-blocking USART transmission
void USART1_Transmit(char data)
{
	TXBUFFER[TXHEAD] = (uint8_t)data;
	TXHEAD++;
	UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(UDRIE);	// enable interrupt for TX buffer empty flag
	/*
	// Wait for empty transmit buffer
	while ( !(UCSR1A & (1<<UDRE1)) );

	// Put data into buffer, sends the data
	UDR1 = data;*/
}

ISR(USART_UDRE_vect)
{
	if (TXTAIL != TXHEAD)
	{
		UDR = TXBUFFER[TXTAIL];
		TXTAIL++;
	}
	else
	{
		UCSRB = _BV(RXEN) | _BV(TXEN);		// disable interrupt if TX buffer is empty
	}
}
//****************************************************

//void sendText(char *ptext)
//{
//	for (unsigned int i = 0; ptext[i] != 0; i++) {
//		USART1_Transmit( ptext[i] );
//	}
//}

void sendText(const char *ptext)
{
	char c;

	for (c = pgm_read_byte(ptext); c ; ++ptext, c = pgm_read_byte(ptext)) {
		USART1_Transmit( c );
	}
}

void sendBin(unsigned char data)
{
	unsigned char i;

	for (i = 0; i < 8; i++)
	{
		if ( (data << i) & 0x80 )
			USART1_Transmit('1');
		else
			USART1_Transmit('0');
	}
}

void sendBCD(char *p_data)
{
	USART1_Transmit( ((*p_data & 0xf0) >> 4) + '0' );
	USART1_Transmit( (*p_data & 0x0f) + '0' );
}

void sendHex(unsigned char data)
{
	if (((data & 0xf0) >> 4) <= 9)
		USART1_Transmit(((data & 0xf0) >> 4) + '0');
	else
		USART1_Transmit((((data & 0xf0) >> 4) - 10) + 'A');

	if ((data & 0x0f) <= 9)
		USART1_Transmit((data & 0x0f) + '0');
	else
		USART1_Transmit(((data & 0x0f) - 10) + 'A');
}


unsigned char USART1_Receive()
{
	// Wait for data to be received
	while ( !(UCSRA & _BV(RXC)) );

	// Get and return received data from buffer
	return UDR;
}

void getLine(char *pIn)
{
	unsigned char i;

	i = 0;
	while (1)
	{
		pIn[i] = USART1_Receive();
		if (pIn[i] == 10)
		break;
		i++;
	}

	pIn[i] = 0;
}
